﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Collections;
using ComponentFactory.Krypton.Toolkit;
using LED_Utils.MultitrackControl;

namespace TrackBarEx
{
	public partial class TimeLinePanel : KryptonPanel,ICustomScale
	{
		public TimeLinePanel()
		{
			InitializeComponent();

            InternalInit();
		}

       
		public TimeLinePanel(IContainer container)
		{
			container.Add(this);

			InitializeComponent();

            InternalInit();
		}

        private void InternalInit()
        {
            _scaleFactor = 200;
            Font = new Font(FontFamily.GenericSansSerif, 8.25f);
            GdiHelper.SetDoubleBuffer(this,true);
        }

		private Hashtable _timelineItems = new Hashtable();

        private static List<double> _layers = new List<double>()
        {
           // 0.01,0.05,0.1,0.2,0.5,1,5,10,30,60
            0.01,0.1,0.5,1,5,10,30,60
        };
		private double GetWidthByLayer(int layer)
		{
            return (double)(ScaleFactor * _layers[layer]);
            //switch (layer )
            //{
            //    case 0:
            //        return ScaleFactor/5;
            //    case 1:
            //        return ScaleFactor;
            //    case 2:
            //        return ScaleFactor*60;
            //    //case 3:
            //    //	return 12000; 
            //    default:
            //        return ScaleFactor*10;
            //}

		}
        public int _scaleFactor;
        [DefaultValue(200) ]
        public int ScaleFactor
        {
            get { return _scaleFactor; }
            set {
                _scaleFactor = value;
                Invalidate();
            }
        }
		private string GetUnitByLayer(int layer)
		{
             double value = _layers[layer];

             if (value >= 1 && value < 60)
                 return "s";
             else if (value == 60)
                 return "m";
             else return string.Empty; 

		}
		private float GetTimeUnit(float seconds)
		{
            float result=0f;
			if (seconds >= 0 && seconds < 1)
			{
                result= seconds;
			}
			else if (seconds >= 1 && seconds < 60)
			{
                result = seconds;
			}
			else if (seconds >= 60 && seconds < 60 * 60 && seconds%60==0)
			{
                result = seconds / 60;
			}
			else if (seconds >= 60 * 60 && seconds < 60 * 60 * 24&& seconds%(60 * 24)==0)
			{
                result = seconds / (60 * 24);//seconds / (60 * 24);
			}
            else return seconds;//(float)Math.Round((double)result, 2);

            return result;

		}

        public Font Font { get; set; }

        static Pen pen = Pens.Gray;
		protected override void OnPaint(PaintEventArgs e)
		{
			base.OnPaint(e);
			_timelineItems.Clear();
			//_timelineItemsDiscionary.Values.OrderBy<TimeLineItem, float>(item->item.);
			int length = this.Width ;
			//int countOfMainLabels = (int)Math.Ceiling ((double)(length / 200));
			//int countOfAuxLabels = (int)Math.Ceiling((double)(length / 100));


			int numberOfLayers = _layers.Count  ;
			for (int i = 0; i < numberOfLayers; i++)
			{
				double width = GetWidthByLayer(i);
                if (width < 5)
                    continue;
				int countOfLabels = (int)Math.Ceiling (((double)length / width));
				for (int j = 0; j < countOfLabels; j++)
				{
					TimeLineItem item = new TimeLineItem();
					if (_timelineItems.ContainsKey(j * width))
					{

						item = (TimeLineItem)_timelineItems[j * width];

						if (item.Layer < i)
						{
							_timelineItems.Remove(j * width);
						}
						//continue;
					}
                    float time = GetTimeUnit((float)(j * width) / (float)ScaleFactor);
                    string timeString = (time == 0) ? time.ToString () : time + GetUnitByLayer(i);
					TimeLineItem newItem = new TimeLineItem() { Layer = i, Width = j * width, Value = timeString };
					_timelineItems.Add(j * width, newItem);
				}

			}
			Brush brush = Brushes.Black;

			//for (int i = 0; i < countOfMainLabels; i++)	
			//{
			//    SizeF stringSize = e.Graphics.MeasureString(i.ToString(), font);

			//    e.Graphics.DrawString(i.ToString(), font, brush, new Point((int)(i * 200-stringSize.Width/2)  , 5));
			//}
			IEnumerator each = _timelineItems.Values.GetEnumerator ();
			int counter = 0;
			while (each.MoveNext())
			{
			//for (int i = 0; i < _timelineItems.Values.Count    ; i++)
			//{
				TimeLineItem item = (TimeLineItem)each.Current;
                //Pen pen = new Pen(Color.FromArgb(255 - item.Layer*2, 0, 0, 0));
                double x = item.Width; //+this.Margin.All *2 ;// - (float)stringSize.Width / 2f;
                double width = GetWidthByLayer(item.Layer);
                if (width > 5)
                {
                    double lineHeigth = (double)(item.Layer * 2 + 3f);
                    e.Graphics.DrawLine(pen, new PointF((float)x, this.Height - (float)(lineHeigth)), new PointF((float)x, this.Height));
                }
                if (width > 40 )
                {
                    SizeF stringSize = e.Graphics.MeasureString(item.Value, Font);

                    if (item.Width == 0)
                        e.Graphics.DrawString(item.Value, Font, brush, new PointF((float)x, 2));
                    else
                        e.Graphics.DrawString(item.Value, Font, brush, new PointF((float)x - (float)(stringSize.Width / 2f), 2));
                }
				counter++;
			//}
			}
            e.Graphics.DrawLine(pen, new PointF(CurrentXLocation, 0), new PointF(CurrentXLocation, this.Height));



		}
        public double _milliseconds;
        public double Milliseconds
        {
            get { return _milliseconds; }
            set {
                if (_milliseconds != value)
                {
                    _milliseconds = value;
                    RefreshCurrentLocation();
                    OnMillisecondsChanged();
                }
               

            }
        }

        private void RefreshCurrentLocation()
        {
            _currentLocation = (int)(_milliseconds * (double)ScaleFactor / 1000);
        }

        private int _currentLocation;
        public int CurrentXLocation
        {
            get {
                int fullCount = _currentLocation / Size.Width;
                //int x
                //Point p = PointToClient(new Point(_currentLocation, 0));
                //return p.X;
                return _currentLocation;
            }
          
        }


        public event EventHandler MillisecondsChanged;
        protected virtual void OnMillisecondsChanged()
        {
            if (MillisecondsChanged != null)
            {
                MillisecondsChanged(this, EventArgs.Empty);
            }
        }


        protected override void OnMouseDown(MouseEventArgs e)
        {
            Milliseconds = (double)e.Location.X / (double)ScaleFactor * 1000;
            base.OnMouseDown(e);
            _currentLocation = e.Location.X;

            _isMouseDown = true;
        }
        bool _isMouseDown = false;
        protected override void OnMouseMove(MouseEventArgs e)
        {
            if (!_isMouseDown)
                return;
            if (e.Location.X < 0)
            {
                Milliseconds=0;
            }

            else
            {
                Milliseconds = (double)e.Location.X / (double)ScaleFactor * 1000;
            }
            base.OnMouseMove(e);
            _currentLocation = e.Location.X;

        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            _isMouseDown = false;
            base.OnMouseUp(e);

        }


		protected override void OnSizeChanged(EventArgs e)
		{
			base.OnSizeChanged(e);
			Invalidate(); 
		}

        #region ICustomScale Members

        public void PerformScale(int percents)
        {
            ScaleFactor = InitialScale * percents / 100;
            RefreshCurrentLocation();
            Invalidate(); 
        }

        private int _initialScale;
        public int InitialScale
        {
            get
            {
                return _initialScale;
            }
            set
            {
                _initialScale = value;
            }
        }

        #endregion



        #region ICustomScale Members

        float _scaleFactor1 = 1;
        float ICustomScale.ScaleFactor
        {
            get
            {
                return _scaleFactor1;
            }
            set
            {
                _scaleFactor1 = value;
            }
        }

        #endregion
    }

	[DebuggerDisplay("Width={Width}")]
	public struct TimeLineItem
	{
		public int Layer { get; set; }
		public double Width { get; set; }
		public string Value { get; set; }
	}
}
